//
//  matrix.h
//  matrix
//
//  Created by Wong Hui Hern on 2023/10/9.
//

#ifndef matrix_h
#define matrix_h
#include <vector>

using namespace std;

template <typename T>
vector<T> operator+(const vector<T> &l, const vector<T> &r){    //向量的加法
    if(l.size()!=r.size()){
        cout<<"The sizes are not same."<<endl;
        exit(-1);
    }
    vector<T> ans;
    for (int i=0;i<l.size();i++){
        ans.push_back(l[i]+r[i]);
    }
    return ans;
}

template <typename T>
vector<T> operator-(const vector<T> &l, const vector<T> &r){    //向量的减法
    if(l.size()!=r.size()){
        cout<<"The sizes are not same."<<endl;
        exit(-1);
    }
    vector<T> ans;
    for (int i=0;i<l.size();i++){
        ans.push_back(l[i]-r[i]);
    }
    return ans;
}

template <typename T>
T operator*(const vector<T> &l, const vector<T> &r){    //向量的乘法
    if(l.size()!=r.size()){
        cout<<"The sizes are not same."<<endl;
        exit(-1);
    }
    T ans;
    for (int i=0;i<l.size();i++){
        ans+=l[i]*r[i];
    }
    return ans;
}

template <typename T>
vector<T> operator*(const T &l, const vector<T> &r){            //向量的左数乘
    vector<T> ans;
    for (int i=0;i<r.size();i++){
        ans.push_back(l*r[i]);
    }
    return ans;
}

template <typename T>
vector<T> operator*(const vector<T> &l, const T &r){            //向量的右数乘
    vector<T> ans;
    for (int i=0;i<l.size();i++){
        ans.push_back(r*l[i]);
    }
    return ans;
}

template <typename T>
vector<vector<T>> operator+(const vector<vector<T>> &l, const vector<vector<T>> &r){    //矩阵相加
    if(l.size()!=r.size()||l[0].size()!=r[0].size()){
            // 处理矩阵维度不匹配的情况
        cout<<"The sizes are not same."<<endl;
        exit(-1);
        }
    vector<vector<T>> ans(l.size(), vector<T>(l[0].size()));
    for (int i = 0; i < l.size(); i++) {
        for (int j = 0; j < l[i].size(); j++) {
            ans[i][j] = l[i][j] + r[i][j];
        }
    }
    return ans;
}

template <typename T>
vector<vector<T>> operator-(const vector<vector<T>> &l, const vector<vector<T>> &r){    //矩阵相减
    if(l.size()!=r.size()||l[0].size()!=r[0].size()){
            // 处理矩阵维度不匹配的情况
        cout<<"The sizes are not same."<<endl;
        exit(-1);
        }
    vector<vector<T>> ans(l.size(), vector<T>(l[0].size()));
    for (int i = 0; i < l.size(); i++) {
        for (int j = 0; j < l[i].size(); j++) {
            ans[i][j] = l[i][j] - r[i][j];
        }
    }
    return ans;
}

template <typename T>
vector<vector<T>> operator*(const vector<vector<T>> &l, const vector<vector<T>> &r){    //矩阵相乘
    if(l[0].size()!=r.size()){
            // 处理矩阵维度不匹配的情况
        cout<<"The sizes are not able to multiply."<<endl;
        exit(-1);
        }
    vector<vector<T>> ans(l.size(), vector<T>(r[0].size()));
    for (int i=0;i<l.size();i++){
        for(int j=0;j<r[0].size();j++){
            ans[i][j]=0;
            for(int k=0;k<r.size();k++){
                ans[i][j]+=l[i][k]*r[k][j];
            }
        }
    }
    return ans;
}

template <typename T>
vector<vector<T>> operator*(const T &l, const vector<vector<T>> &r){    //矩阵左数乘
    vector<vector<T>> ans(r.size(), vector<T>(r[0].size()));
    for (int i = 0; i < r.size(); i++) {
        for (int j = 0; j < r[i].size(); j++) {
            ans[i][j] = l*r[i][j];
        }
    }
    return ans;
}

template <typename T>
vector<vector<T>> operator*(const vector<vector<T>> &l, const T &r){    //矩阵右数乘
    vector<vector<T>> ans(l.size(), vector<T>(l[0].size()));
    for (int i = 0; i < l.size(); i++) {
        for (int j = 0; j < l[i].size(); j++) {
            ans[i][j] = l[i][j]*r;
        }
    }
    return ans;
}

class matrix {
private:
    double ans;
    vector<double> vec;
    vector<vector<double>> matr;
    
public:
    void get_ans();
    void get_vec();
    void get_matr();
    vector<double> add(vector<double> l,vector<double> r);
    vector<double> minus(vector<double> l,vector<double> r);
    double multiply(vector<double> l,vector<double> r);
    vector<double> num_multiply(double l,vector<double> r);
    vector<double> num_multiply(vector<double> l,double r);
    vector<vector<double>> add(vector<vector<double>> l,vector<vector<double>> r);
    vector<vector<double>> minus(vector<vector<double>> l,vector<vector<double>> r);
    vector<vector<double>> multiply(vector<vector<double>> l,vector<vector<double>> r);
    vector<vector<double>> num_multiply(double l,vector<vector<double>> r);
    vector<vector<double>> num_multiply(vector<vector<double>> l,double r);
};

void matrix::get_ans(){
    cout<<ans;
}

void matrix::get_vec(){
    for(int i=0;i<vec.size();i++){
        cout<<vec[i]<<" ";
    }
}

void matrix::get_matr(){
    for(int i=0;i<matr.size();i++){
        for(int j=0;j<matr[0].size();j++){
            cout<<matr[i][j]<<" ";
        }
        cout<<endl;
    }
}

vector<double> matrix::add(vector<double> l,vector<double> r){
    vec=l+r;
    return vec;
}

vector<double> matrix::minus(vector<double> l,vector<double> r){
    vec=l-r;
    return vec;

}

double matrix::multiply(vector<double> l,vector<double> r){
    ans=l*r;
    return ans;
}

vector<double> matrix::num_multiply(double l,vector<double> r){
    vec=l*r;
    return vec;
}

vector<double> matrix::num_multiply(vector<double> l,double r){
    vec=l*r;
    return vec;
}

vector<vector<double>> matrix::add(vector<vector<double>> l,vector<vector<double>> r){
    matr=l+r;
    return matr;
}

vector<vector<double>> matrix::minus(vector<vector<double>> l,vector<vector<double>> r){
    matr=l-r;
    return matr;
}

vector<vector<double>> matrix::multiply(vector<vector<double>> l,vector<vector<double>> r){
    matr=l*r;
    return matr;
}

vector<vector<double>> matrix::num_multiply(double l,vector<vector<double>> r){
    matr=l*r;
    return matr;
}

vector<vector<double>> matrix::num_multiply(vector<vector<double>> l,double r){
    matr=l*r;
    return matr;
}

#endif /* matrix_h */

